﻿using System;
using System.Collections.Generic;

namespace Framework.Event
{

    public class EventManager : FrameworkComponent
    {

        private Dictionary<int, List<EventHandler<GameEventArgs>>> m_eventHandlers =
            new Dictionary<int, List<EventHandler<GameEventArgs>>>();


        /// <summary>
        /// 待处理的事件
        /// </summary>
        private Queue<KeyValuePair<object, GameEventArgs>> processEventqQueue =
            new Queue<KeyValuePair<object, GameEventArgs>>();
        /// <summary>
        /// 订阅事件处理函数。
        /// </summary>
        /// <param name="id">事件类型编号。</param>
        /// <param name="handler">要订阅的事件处理函数。</param>
        public void Subscribe(int id, EventHandler<GameEventArgs> handler)
        {
            if (!m_eventHandlers.ContainsKey(id))
            {
                m_eventHandlers.Add(id,new List<EventHandler<GameEventArgs>>());
            }
            m_eventHandlers[id].Add(handler);
        }

        /// <summary>
        /// 取消订阅事件处理函数。
        /// </summary>
        /// <param name="id">事件类型编号。</param>
        /// <param name="handler">要取消订阅的事件处理函数。</param>
        public void Unsubscribe(int id, EventHandler<GameEventArgs> handler)
        {
            if (m_eventHandlers.ContainsKey(id))
            {
                m_eventHandlers[id].Remove(handler);
            }
        }

        public void Fire(object sender,GameEventArgs eventArgs)
        {
            processEventqQueue.Enqueue(new KeyValuePair<object, GameEventArgs>(sender,eventArgs));
        }

        void ProcessEvent()
        {
            while (processEventqQueue.Count>0)
            {
                var kv = processEventqQueue.Dequeue();
                int eventId = kv.Value.Id;
                if (m_eventHandlers.ContainsKey(eventId))
                {
                    foreach (var eventHandler in m_eventHandlers[eventId])
                    {
                        eventHandler.Invoke(kv.Key,kv.Value);
                    }
                }
                ReferencePool.Release(kv.Value);
            }
        }
        public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
        {
            ProcessEvent();
        }

        public override void Shutdown()
        {
            m_eventHandlers.Clear();
        }
    }

}